class Rudoku::Field
  attr_reader :possibilities, :x, :y, :sudoku
  attr_accessor :guessed, :given
  
  def initialize(sudoku, x, y)
    @sudoku = sudoku
    @possibilities = (1..9).to_a
    @x = x
    @y = y
    @guessed = false
  end
  
  def remove(numbers)
    numbers = [*numbers] # this works for a single number and for ranges, too
    new_possibilities = @possibilities - numbers
    
    if new_possibilities == @possibilities # no change
      return false
    elsif new_possibilities.size >= 1        
      @possibilities = new_possibilities
      @sudoku.changed = true
      return true
    else
      return false # no change
    end
  end
  
  def set_possibilities(p) # backdoor for the bruteforcer; has to be able to reset possibilities after backtracking
    @possibilities = [*p].uniq
    @sudoku.changed = true
  end
  
  def position
    (?A + x).chr + (y + 1).to_s # 2, 3 => B3
  end
  
  def solved?
    @possibilities.size == 1
  end
  
  def value
    solved? ? @possibilities[0] : nil
  end
  
  def value=(number)
    remove((1..9).to_a - [*number])
  end
  
  def guess(number)
    @guessed = true
    self.value = number
    puts "GUESSING #{position} = #{number}" if $debug
  end
  
  def guessed?
    @guessed
  end
  
  def given?
    @given
  end
  
  def to_s
    str = solved? ? value.to_s : "."

    if $enable_color
      if guessed?
        str = "\e[31m#{str}\e[0m"
      elsif !given?
        str = "\e[32m#{str}\e[0m"
      end
    end
        
    str
  end
  
  def containing_square_pos
    @sudoku.containing_square_pos(@x, @y)
  end
  
  def containing_square
    @sudoku.containing_square(@x, @y)
  end
  
  def containing_row
    @sudoku.rows[@y]
  end
  
  def containing_column
    @sudoku.columns[@x]
  end
  
  def containing_houses
    [containing_square, containing_row, containing_column]
  end
  
  def seen_fields # includes the field itself!
    containing_houses.union
  end
  
  def seen_fields_prioritized # the field itself occurs thrice, the other fields in the line/box intersections occur twice
    containing_row + containing_column + containing_square
  end
  
  def sees?(f) # true if fields share a house
    containing_houses.include?(f)
  end
  
  alias :seen_by? :sees?
end
